package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"syscall"
	"time"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/dialog"
	"fyne.io/fyne/v2/layout"
	"fyne.io/fyne/v2/widget"

	"tool/utils"
	"tool/utils/sql"
	"tool/utils/sql/models"
	"github.com/fsnotify/fsnotify"
)

var version string = "0.0.3"

type config struct {
	MainWindow      fyne.Window
	FildMoveList    *widget.List
	List            []models.FileMoveList
	FildMove        FildMoveClass
	ServiceStart    ServiceStartClass
	StartCommondBtn *widget.Button
}

var cfg config

type FildMoveClass struct {
	Id      string
	Name    string
	OrgPath string
	NewPath string
}

type ServiceStartClass struct {
	Id    string
	Name  string
	Value string
}

func main() {

	sql.ConnectDB()
	utils.Inits()
	a := app.New()
	//创建一个窗口
	w := a.NewWindow("工具管理器 " + version)
	cfg.MainWindow = w

	allLayout := cfg.makeUI()

	w.SetContent(allLayout)
	// 设置窗口大小,
	w.Resize(fyne.NewSize(500, 350))
	// 窗口居中
	w.CenterOnScreen()
	//设置主窗口
	w.SetMaster()

	//展示窗口 并运行程序
	w.ShowAndRun()
}

// 初始化界面
func (app *config) makeUI() fyne.CanvasObject {

	fileMoveBtn := widget.NewButton("文件移动", func() {})
	fileMoveBtn.OnTapped = app.fileMoveFunc()

	tiktokBtn := widget.NewButton("抖音服务商", func() {
		utils.OpenExe("D:/raymond/tiktok-audit-tool/", "tiktok-audit-tool.exe")
	})
	accountManageBtn := widget.NewButton("账号管理", func() {
		utils.OpenExe("D:/raymond/account-manage/", "account-manage.exe")
	})
	md5Btn := widget.NewButton("md5加密", func() {
		md5Encryption := app.md5Encryption()
		md5Encryption()
	})
	qrCodeBtn := widget.NewButton("生成二维码", func() {
		generateQRcode := app.generateQRcode()
		generateQRcode()
	})
	logFileSegmentationBtn := widget.NewButton("日志文件切割(测试版)", func() {
		startSegmentation := app.startSegmentation()
		startSegmentation()
	})
	//
	setEnvBtn := widget.NewButton("设置环境变量", func() {
		setEnv := app.setEnv()
		setEnv()
	})
	//
	urlEncodingBtn := widget.NewButton("URL编码", func() {
		urlEncoding := app.urlEncoding()
		urlEncoding()
	})
	//
	serviceStartupBtn := widget.NewButton("服务启动", func() {
		serviceStartup := app.serviceStartup()
		serviceStartup()
	})

	// 使用两列的GridLayout
	allLayout := container.New(layout.NewGridLayoutWithRows(3), fileMoveBtn, tiktokBtn, accountManageBtn, md5Btn, qrCodeBtn, logFileSegmentationBtn, setEnvBtn, urlEncodingBtn, serviceStartupBtn)

	return allLayout
}

// 文件移动
func (app *config) fileMoveFunc() func() {
	return func() {

		w := fyne.CurrentApp().NewWindow("文件移动")

		app.List = sql.QueryFileMoveList("select * from file_move order by id desc")

		addBtn := widget.NewButton("添加配置", app.addFileMoveFunc("insert"))
		refreshBtn := widget.NewButton("刷新", func() {})
		var refreshList func()

		app.FildMoveList = widget.NewList(
			func() int {
				return len(app.List)
			},
			func() fyne.CanvasObject {

				name := widget.NewButton("名称", func() {})

				name1 := widget.NewLabel("原始路径")
				name2 := widget.NewLabel("新的路径")
				startMoveBtn := widget.NewButton("开始移动", func() {})
				startListenBtn := widget.NewButton("开启监听", func() {})
				closeListenBtn := widget.NewButton("取消监听", func() {})

				deleteBtn := widget.NewButton("删除", func() {})
				createTestPkgBtn := widget.NewButton("打测试包", func() {})
				createOfficialPkgBtn := widget.NewButton("打正试包", func() {})

				// return container.New(layout.NewHBoxLayout(), name, name1, name2, deleteBtn, startMoveBtn)
				// return container.New(layout.NewVBoxLayout(), container.New(layout.NewHBoxLayout(), name, name1, name2, startMoveBtn), container.New(layout.NewHBoxLayout(), deleteBtn, createTestPkgBtn, createOfficialPkgBtn))
				return container.New(layout.NewVBoxLayout(), container.New(layout.NewHBoxLayout(), name, name1, name2, startMoveBtn,startListenBtn,closeListenBtn), container.New(layout.NewHBoxLayout(), deleteBtn, createTestPkgBtn, createOfficialPkgBtn), container.New(layout.NewHBoxLayout(), widget.NewLabel("")))
			},
			func(index widget.ListItemID, o fyne.CanvasObject) {
				objects := o.(*fyne.Container).Objects[0].(*fyne.Container).Objects
				objects1 := o.(*fyne.Container).Objects[1].(*fyne.Container).Objects

				length := 15
				if len(app.List[index].Name) > length {
					objects[0].(*widget.Button).SetText(app.List[index].Name[0:length] + "...")
				} else {
					// fmt.Println(len(app.List[index].Name))
					if len(app.List[index].Name) == 15 {
						objects[0].(*widget.Button).SetText(app.List[index].Name + "       ")
					} else if len(app.List[index].Name) == 12 {
						objects[0].(*widget.Button).SetText(app.List[index].Name + "         ")
					} else if len(app.List[index].Name) == 9 {
						objects[0].(*widget.Button).SetText(app.List[index].Name + "           ")
					} else {
						objects[0].(*widget.Button).SetText(app.List[index].Name + "             ")
					}
				}
				objects[0].(*widget.Button).OnTapped = func() {
					app.FildMove = FildMoveClass{Id: strconv.Itoa(app.List[index].Id), Name: app.List[index].Name, OrgPath: app.List[index].OrgPath, NewPath: app.List[index].NewPath}
					fileMoveFunc := app.addFileMoveFunc("edit") // 获取函数
					fileMoveFunc()                              // 执行函数
				}
				/* objects[1].(*widget.Label).SetText(app.List[index].OrgPath)
				objects[2].(*widget.Label).SetText(app.List[index].NewPath) */

				objects[3].(*widget.Button).OnTapped = func() {
					srcDir := app.List[index].OrgPath
					dstDir := app.List[index].NewPath
					if err := copyFolder(srcDir, dstDir); err != nil {
						fmt.Println("Error copying files:", err)
					} else {
						fmt.Println("Files copied successfully.")
						toast("移动数据成功", w)
					}
				}
				objects[4].(*widget.Button).OnTapped = func() {
					srcDir := app.List[index].OrgPath
					// dstDir := app.List[index].NewPath
					startListenFolder(srcDir)
				}
				objects[5].(*widget.Button).OnTapped = func() {
					
				}


				// o.(*fyne.Container).Objects[1].(*widget.Label).SetText("__")
				//删除
				objects1[0].(*widget.Button).OnTapped = func() {

					cnf := dialog.NewConfirm("提示", "您是否要删除", func(response bool) {
						if response {
							sql.Delete("delete from file_move where id=?", strconv.Itoa(app.List[index].Id))

							/* app.List = sql.QueryFileMoveapp.List("select * from file_move order by id desc")
							// 刷新列表组件
							o.(*fyne.Container).Refresh() */
							refreshList()
						}
					}, w)
					cnf.SetDismissText("取消")
					cnf.SetConfirmText("确认")
					cnf.Show()
				}
				//打测试包
				objects1[1].(*widget.Button).OnTapped = func() {

					var err error
					// var parts []string
					// parts, err = shlex.Split(list[index].OrgPath)
					// command := parts[0]
					// args := parts[1:]
					// cmd := exec.Command(list[index].OrgPath, "npm run build:test")
					cmd := exec.Command("npm", "run", "build:test")
					cmd.Dir = "D:/web_project/zhixiaoer_dc_view/" // 关键设置
					// 设置标准输出和错误
					cmd.Stdout = os.Stdout
					cmd.Stderr = os.Stderr
					// 执行命令
					err = cmd.Run()
					if err != nil {
						log.Fatalf("命令执行失败: %v", err)
					}
					fmt.Println("successfully.")
					toast("移动数据成功", w)

					if exitErr, ok := err.(*exec.ExitError); ok {
						// 获取退出状态码
						status := exitErr.Sys().(syscall.WaitStatus)
						exitCode := status.ExitStatus()
						fmt.Printf("命令执行失败，退出码: %d\n", exitCode)
					} else if err != nil {
						// 其他类型错误（如命令不存在）
						fmt.Printf("执行错误: %v\n", err)
					} else {
						fmt.Println("命令执行成功")
					}
				}
			},
		)

		refreshList = func() {
			app.List = sql.QueryFileMoveList("select * from file_move order by id desc")
			// 刷新列表组件
			app.FildMoveList.Refresh()
		}
		refreshBtn.OnTapped = refreshList

		rowLayout_1 := container.New(layout.NewHBoxLayout(), addBtn, refreshBtn)
		rowLayout_2 := container.New(layout.NewVBoxLayout(), rowLayout_1, widget.NewLabel(""))
		allLayout := container.NewBorder(rowLayout_2, nil, nil, nil, app.FildMoveList)
		w.SetContent(allLayout)

		// w.SetFixedSize(true) // 设置固定大小，避免用户拖动改变大小

		// start 监听主窗口的关闭事件
		// 前提是必须设置主窗口
		w.SetOnClosed(func() {
			w.Close()
		})
		// end 监听主窗口的关闭事件

		// 设置窗口大小,
		w.Resize(fyne.NewSize(600, 400))
		w.CenterOnScreen()
		w.Show()
	}
}

// 添加文件移动数据
func (app *config) addFileMoveFunc(types string) func() {
	return func() {
		title := "添加文件移动"
		if types == "insert" {
			title = "添加文件移动"
		} else {
			title = "编辑文件移动"
		}
		w := fyne.CurrentApp().NewWindow(title)

		nameLabel := widget.NewLabel("名称    ")
		nameInput := widget.NewEntry()
		nameInput.SetPlaceHolder("请输入名称")
		rowLayout_1 := container.NewBorder(nil, nil, nameLabel, layout.NewSpacer(), nameInput)

		nameOrgPathLabel := widget.NewLabel("原始路径")
		nameOrgPathInput := widget.NewEntry()
		nameOrgPathInput.SetPlaceHolder("需要移动的文件夹路径")
		nameOrgPathInput.Wrapping = 2     // 开启自动换行
		nameOrgPathInput.MultiLine = true //多行输入
		rowLayout_2 := container.NewBorder(nil, nil, nameOrgPathLabel, layout.NewSpacer(), nameOrgPathInput)

		nameNewPathLabel := widget.NewLabel("新的路径")
		nameNewPathInput := widget.NewEntry()
		nameNewPathInput.SetPlaceHolder("最终位置的文件夹路径")
		nameNewPathInput.Wrapping = 2     // 开启自动换行
		nameNewPathInput.MultiLine = true //多行输入
		rowLayout_3 := container.NewBorder(nil, nil, nameNewPathLabel, layout.NewSpacer(), nameNewPathInput)

		commonPathLabel := widget.NewLabel("命令打包路径")
		commonPathInput := widget.NewEntry()
		commonPathInput.SetPlaceHolder("执行打包命令的文件夹路径,没有命令打包路径则不填")
		commonPathInput.Wrapping = 2     // 开启自动换行
		commonPathInput.MultiLine = true //多行输入
		rowLayout_4 := container.NewBorder(nil, nil, commonPathLabel, layout.NewSpacer(), commonPathInput)

		if types == "insert" {
			nameInput.SetText("")
			nameOrgPathInput.SetText("")
			nameNewPathInput.SetText("")
			commonPathInput.SetText("")
		} else {
			nameInput.SetText(app.FildMove.Name)
			nameOrgPathInput.SetText(app.FildMove.OrgPath)
			nameNewPathInput.SetText(app.FildMove.NewPath)
			commonPathInput.SetText(app.FildMove.NewPath)
		}

		saveBtn := widget.NewButton("保存", func() {
			if types == "insert" {
				sql.Insert("insert into file_move (name,org_path,new_path) VALUES(?,?,?)", nameInput.Text, nameOrgPathInput.Text, nameNewPathInput.Text)
			} else {
				sql.Update("update file_move set name=?,org_path=?,new_path=? where id=?", nameInput.Text, nameOrgPathInput.Text, nameNewPathInput.Text, app.FildMove.Id)
			}

			app.List = sql.QueryFileMoveList("select * from file_move order by id desc")
			// 刷新列表组件
			app.FildMoveList.Refresh()

			w.Close()

		})

		allLayout := container.New(layout.NewVBoxLayout(), rowLayout_1, rowLayout_2, rowLayout_3, rowLayout_4, saveBtn)

		w.SetContent(allLayout)
		// w.SetFixedSize(true) // 设置固定大小，避免用户拖动改变大小
		// start 监听主窗口的关闭事件
		// 前提是必须设置主窗口
		w.SetOnClosed(func() {
			w.Close()
		})
		// edn 监听主窗口的关闭事件

		// 设置窗口大小,
		w.Resize(fyne.NewSize(450, 250))
		w.CenterOnScreen()
		w.Show()
	}
}
//开启监听文件夹
func startListenFolder(dirToWatch string) {
    // 创建一个新的监控器
    watcher, err := fsnotify.NewWatcher()
    if err != nil {
        log.Fatal(err)
    }
    defer watcher.Close()

    // 要监控的目录
    // dirToWatch := "."
    err = watcher.Add(dirToWatch)
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("开始监控目录: %s", dirToWatch)

    // 启动一个无限循环来监听事件
    done := make(chan bool)
    go func() {
        for {
            select {
            case event, ok := <-watcher.Events:
                if!ok {
                    return
                }
                log.Printf("发生事件: %s %s", event.Name, event.Op)
            case err, ok := <-watcher.Errors:
                if!ok {
                    return
                }
                log.Printf("发生错误: %v", err)
            }
        }
    }()

    // 保持程序运行
    <-done
}
//取消监听
func ss(){
	// 当需要取消所有监听时
	watcher.Close() // 这会关闭事件通道并释放所有资源
}

// CopyFile 复制单个文件
func CopyFile(src, dst string) error {
	sourceFile, err := os.Open(src)
	if err != nil {
		return err
	}
	defer sourceFile.Close()

	destFile, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer destFile.Close()

	_, err = io.Copy(destFile, sourceFile)
	if err != nil {
		return err
	}

	// 注意：通常不需要显式调用Sync，因为Close会刷新缓冲区
	// 如果需要确保数据立即写入磁盘，可以取消注释下一行
	// if err := destFile.Sync(); err != nil {
	// 	return err
	// }

	return nil
}
func copyFolder(src string, dst string) error {
	// 创建目标文件夹
	err := os.MkdirAll(dst, 0755)
	if err != nil {
		return err
	}

	// 读取源文件夹中的所有文件和子文件夹
	files, err := ioutil.ReadDir(src)
	if err != nil {
		return err
	}

	// 遍历源文件夹中的每个文件和子文件夹
	for _, file := range files {
		srcPath := filepath.Join(src, file.Name())
		dstPath := filepath.Join(dst, file.Name())

		// 如果是子文件夹，递归调用copyFolder函数
		if file.IsDir() {
			err = copyFolder(srcPath, dstPath)
			if err != nil {
				return err
			}
		} else {
			// 如果是文件，直接复制到目标文件夹
			err = CopyFile(srcPath, dstPath)
			if err != nil {
				return err
			}
		}
	}

	return nil
}

// 提示弹窗
func toast(title string, win fyne.Window) {
	// infoDialog := dialog.ShowInformation("提示", title, win)

	// 创建一个信息对话框
	infoDialog := dialog.NewInformation("提示", title, win)

	// 显示信息对话框
	infoDialog.Show()

	// 使用 time.AfterFunc 在指定时间后关闭对话框
	time.AfterFunc(2*time.Second, func() {
		infoDialog.Hide()
	})
}
